#include "Poller.hpp"
#include "Channel.hpp"  // Channel类  内含fd和感兴趣事件

#include <cstring>
#include <iostream>

Poller::Poller(int maxEvents)
    : epollFd_(::epoll_create1(EPOLL_CLOEXEC)),
      events_(maxEvents)
{
    if (epollFd_ < 0) {
        std::cerr << "Failed to create epoll fd\n";
        ::exit(EXIT_FAILURE);
    }
}

Poller::~Poller() {
    if (epollFd_ >= 0) {
        ::close(epollFd_);
    }
}

int Poller::poll(int timeoutMs, std::vector<Channel*>& activeChannels) {
    int numEvents = ::epoll_wait(epollFd_, &*events_.begin(), static_cast<int>(events_.size()), timeoutMs);
    if (numEvents < 0) {
        if (errno != EINTR) {
            perror("epoll_wait error");
        }
        return 0;
    }

    for (int i = 0; i < numEvents; ++i) {
        Channel* channel = static_cast<Channel*>(events_[i].data.ptr);
        channel->setRevents(events_[i].events);
        activeChannels.push_back(channel);
    }

    // 如果事件数组满了，扩容
    if (static_cast<size_t>(numEvents) == events_.size()) {
        events_.resize(events_.size() * 2);
    }

    return numEvents;
}

bool Poller::addChannel(Channel* channel) {
    epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = channel->getEvents();
    ev.data.ptr = channel;
    if (::epoll_ctl(epollFd_, EPOLL_CTL_ADD, channel->getFd(), &ev) < 0) {
        perror("epoll_ctl add failed");
        return false;
    }
    return true;
}

bool Poller::updateChannel(Channel* channel) {
    epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = channel->getEvents();
    ev.data.ptr = channel;
    if (::epoll_ctl(epollFd_, EPOLL_CTL_MOD, channel->getFd(), &ev) < 0) {
        perror("epoll_ctl mod failed");
        return false;
    }
    return true;
}

bool Poller::removeChannel(Channel* channel) {
    // epoll_ctl 的删除操作忽略event参数，可传NULL
    if (::epoll_ctl(epollFd_, EPOLL_CTL_DEL, channel->getFd(), nullptr) < 0) {
        perror("epoll_ctl del failed");
        return false;
    }
    return true;
}
